package com.deyuanyun.pic.settings.service.msgtemplate;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.deyuanyun.pic.common.spring.SpringAppliction;
import com.deyuanyun.pic.common.util.CommonUtil;
import com.deyuanyun.pic.common.util.StringUtils;
import com.deyuanyun.pic.settings.controller.dto.BizMsgThresholdVO;
import com.deyuanyun.pic.settings.controller.dto.base.NewlyTaskDTO;
import com.deyuanyun.pic.settings.controller.dto.base.PigTaskDTO;
import com.deyuanyun.pic.settings.controller.pipe.vo.PipeLocationDTO;
import com.deyuanyun.pic.settings.domain.base.BizMsgUser;
import com.deyuanyun.pic.settings.domain.pipe.PipeLine;
import com.deyuanyun.pic.settings.enumeration.ThresholdType;
import com.deyuanyun.pic.settings.service.pipe.PipeLocationService;
import com.deyuanyun.pic.settings.support.utils.PipeDictUtils;
import com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 *  内检测数据录入消息推送
 *  @author axiao(xj08.dream@gmail.com)
 *  @date 2016-08-10
 *  @version 1.0
 *  Histroy: [修改人][时间][描述]
 */
public class InspResultInputPushMsg extends AbstractPushMsgTemplate {

    private static final Logger LOGGER = LoggerFactory.getLogger(InspResultInputPushMsg.class);

    /** 检测任务id key */
    public static final String TASK_ID_KEY = "taskId";
    /** 检测任务名字 key */
    public static final String TASK_NAME_KEY = "taskName";
    /** 缺陷类型 key */
    public static final String FEATURE_TYPE_KEY = "featureType";
    /** 创建备注 */
    private String createRemark = "";

    @Override
    public void doPushMsgData() {
        if(!super.isInterface) {//当是否接口调用为false的时候不允许向下执行
            LOGGER.info("不是接口调用，不允许执行");
            return;
        }
        if(super.interfaceParam.isEmpty()) {
            LOGGER.info("没有传入接口参数");
            return;
        }
        Map<String, Object> inteMap = super.interfaceParam;
        Object taskNameObj = inteMap.get(TASK_NAME_KEY);
        Object taskIdObj = inteMap.get(TASK_ID_KEY);
        Object featureTypeObj = inteMap.get(FEATURE_TYPE_KEY);
        if(taskNameObj == null || taskIdObj == null || featureTypeObj == null) {//其中任何参数任何一个为空都不允许向下执行
            if (LOGGER.isInfoEnabled())
                LOGGER.info("参数有空值存在，不允许向下执行");
            return;
        }
        String featureType = featureTypeObj.toString();
        LOGGER.info("缺陷类型为：" + featureType);
        boolean isMetalLoss = false; //是不是金属损失
        /**
         * featureType为金属损失时的说明
         * 1、导入数据  没有内、外部金属损失，类型为  "金属损失";
         * 2、导入数据  有内外部金属损失，类型为  "金属损失,外部金属损失,内部金属损失";
         * 3、导入数据  （只有外部金属损失）或（外部金属损失和其他金属损失），类型为  "金属损失,外部金属损失";
         * 4、导入数据  （只有内部金属损失）或（内部金属损失和其他金属损失），类型为  "金属损失,内部金属损失";
         */
        List<String> featureTypeList = Arrays.asList(featureType.split(","));
        if(featureTypeList.contains(JSSS_STR)) { //为金属损失时
            isMetalLoss = true;
        }
        super.thresListCastString(Lists.newArrayList(taskNameObj.toString(), isMetalLoss ? JSSS_STR : featureType));
        this.createRemark = "内检测数据录入消息推送";
        BizMsgThresholdVO inspResult = bizMsgThresholdService.queryDataByTypeOne(ThresholdType.INTERNAL_INSP_RESULT_INPUT.getValue());
        //提醒所有用户内检测数据已经导入
        initializeBizMsgSends(inspResult);

        //提醒对应的角色，内检测数据已经导入，请开展内检测数据评价工作
        BizMsgThresholdVO inspAppraise = bizMsgThresholdService.queryDataByTypeOne(ThresholdType.INTERNAL_INSP_APPRAISE.getValue());
        super.roleList = inspAppraise.getRoleIdList();
        super.thresListCastString(Lists.newArrayList(taskNameObj.toString(), isMetalLoss ? JSSS_STR : featureType));
        this.createRemark = "内检测数据录入,提醒开展数据评价消息推送";
        initializeBizMsgSends(inspAppraise);

        //当内检测结果录入中的类型为金属损失时,对比分析来推送消息
        if(isMetalLoss) {
            initMetalossBizSends(taskIdObj.toString(), featureTypeList);
        }
    }

    private String JSSS_STR  = "金属损失";

    private String WB_JSSS_STR = "外部金属损失";

    private String NB_JSSS_STR  = "内部金属损失";

    /**
     * 推送金属损失消息，其中缺陷类型分为三种，金属损失,内部金属损失、外部金属损失多种组合，其中金属损失类型一定存在
     * @param taskId 检测任务id
     * @param featureTypeList 缺陷类型
     */
    private void initMetalossBizSends(String taskId, List<String> featureTypeList){
        //根据检测任务id得到按照时间降序排的前两条记录的检测任务id
        PigTaskDTO pigTaskDTO = super.bizMsgThresholdService.findPigTaskById(taskId);

        if(pigTaskDTO == null)
            return;

        String pipeLineId = pigTaskDTO.getPipeLineId(); //管道id

        List<NewlyTaskDTO> newlyTasks = super.bizMsgThresholdIntefaceService.queryNewlyTask(pipeLineId,
                pigTaskDTO.getFromPipeValveroomId(), pigTaskDTO.getToPipeValveroomId());
        if(newlyTasks != null && newlyTasks.size() == 2) {
            String oneTaskId = newlyTasks.get(0).getTaskId();
            String twoTaskId = newlyTasks.get(1).getTaskId();

            if(StringUtils.isNotEmpty(oneTaskId) && StringUtils.isNotEmpty(twoTaskId)) {
                if(featureTypeList.contains(NB_JSSS_STR) || featureTypeList.contains(JSSS_STR)) { //缺陷类型有内部金属损失的时候才推送消息
                    //内部金属损失1
                    NewlyTaskDTO insideMetaLoss1 = super.bizMsgThresholdIntefaceService.queryMetalLoss(pipeLineId, oneTaskId, "0");
                    //内部金属损失2
                    NewlyTaskDTO insideMetaLoss2 = super.bizMsgThresholdIntefaceService.queryMetalLoss(pipeLineId, twoTaskId, "0");

                    if (insideMetaLoss1 != null && insideMetaLoss2 != null) {
                        float featureCount1 = insideMetaLoss1.getFeatureCount();
                        float featureCount2 = insideMetaLoss2.getFeatureCount();
                        //查询内部金属损失阀值信息
                        BizMsgThresholdVO bizMsgThresholdVO = bizMsgThresholdService.queryDataByTypeOne(ThresholdType.INTERNAL_INSP_INSIDE_METAL_LOSS.getValue());
                        metaLossMsgSend(pipeLineId, bizMsgThresholdVO, "内部金属损失消息推送", featureCount1, featureCount2);
                    }
                }
                if(featureTypeList.contains(WB_JSSS_STR) || featureTypeList.contains(JSSS_STR)) { //缺陷类型有外部金属损失的时候才推送消息
                    //外部金属损失1
                    NewlyTaskDTO outsideMetaLoss1 = super.bizMsgThresholdIntefaceService.queryMetalLoss(pipeLineId, oneTaskId, "1");
                    //外部金属损失2
                    NewlyTaskDTO outsideMetaLoss2 = super.bizMsgThresholdIntefaceService.queryMetalLoss(pipeLineId, twoTaskId, "1");

                    if (outsideMetaLoss1 != null && outsideMetaLoss2 != null) {
                        float featureCount1 = outsideMetaLoss1.getFeatureCount();
                        float featureCount2 = outsideMetaLoss2.getFeatureCount();
                        //查询外部金属损失阀值信息
                        BizMsgThresholdVO bizMsgThresholdVO = bizMsgThresholdService.queryDataByTypeOne(ThresholdType.INTERNAL_INSP_OUTSIDE_METAL_LOSS.getValue());
                        metaLossMsgSend(pipeLineId, bizMsgThresholdVO, "外部金属损失消息推送", featureCount1, featureCount2);
                    }
                }
            }
        }
    }

    /**
     * 内部金属损失、外部金属损失，根据增长比推送消息
     * @param pipeLineId
     * @param bizMsgThresholdVO
     * @param createRemark
     * @param segmentCount1
     * @param segmentCount2
     */
    private void metaLossMsgSend(String pipeLineId, BizMsgThresholdVO bizMsgThresholdVO, String createRemark ,
                                 float segmentCount1, float segmentCount2) {
        if(bizMsgThresholdVO !=null && bizMsgThresholdVO.getThresholdContent() != null) {
            JSONObject jsonObject = JSON.parseObject(bizMsgThresholdVO.getThresholdContent());
            float insideLoss =  jsonObject.getFloatValue("percent");
            if (((segmentCount1 - segmentCount2) / segmentCount2) * 100 >= insideLoss) { //这两次计算出来的增长率大于设置的大小的时候推送消息，数据库里面存的值是乘100的
                super.roleList = bizMsgThresholdVO.getRoleIdList();
                PipeLine pipeLine = PipeDictUtils.getLineById(pipeLineId);
                if(pipeLine != null) {
                    PipeLocationService pipeLocationService = SpringAppliction.getBean(PipeLocationService.class);

                    PipeLocationDTO fromLocation= pipeLocationService.queryPipeLocationById(pipeLineId ,pipeLine.getFromPipeValveroomId());
                    PipeLocationDTO toLocation = pipeLocationService.queryPipeLocationById(pipeLineId, pipeLine.getToPipeValveroomId());
                    if(fromLocation != null && toLocation != null)
                        super.thresListCastString(Lists.newArrayList(pipeLine.getName(), fromLocation.getName(), toLocation.getName()));
                }
                this.createRemark = createRemark;
                initializeBizMsgSends(bizMsgThresholdVO);
            }
        }
    }

    /**
     * @param args 参数说明：
     * <pre>
     * arg[0]：为业务阀值实体信息，类型为：{@link BizMsgThresholdVO}<br />
     * </pre>
     */
    @Override
    public void initializeBizMsgSends(Object... args) {
        BizMsgThresholdVO bizMsgThresholdVO = (BizMsgThresholdVO) args[0];
        String thresholdId = bizMsgThresholdVO.getId();

        String msgContent = bizMsgThresholdVO.getMsgContent();
        BizMsgUser bizMsgUser = new BizMsgUser();
        bizMsgUser.setCreateRemark(this.createRemark);
        bizMsgUser.setCreateDate(new Date());
        if (StringUtils.isNotEmpty(msgContent))//消息内容不为空的时候设置到消息推送实体类
            bizMsgUser.setMsgContent(msgContent);
        if (StringUtils.isNotEmpty(super.thresholdContent)) { //设置阀值内容
            bizMsgUser.setThresholdContent(super.thresholdContent);
        }
        List<MsgQueue.BizMsgUserInfo> userInfos = new ArrayList<MsgQueue.BizMsgUserInfo>();
        if (super.roleList != null && !super.roleList.isEmpty()) {
            Set<String> userIds = super.bizMsgThresholdService.queryUseIdByRoleIds(super.roleList); //用户id集合
            for (String userId : userIds) {
                BizMsgUser msgUser = new BizMsgUser();
                BeanUtils.copyProperties(bizMsgUser, msgUser);
                msgUser.setUserId(userId);
                msgUser.setId(CommonUtil.getUUID());

                userInfos.add(msgQueue.new BizMsgUserInfo().setValid(false).setBizMsgUser(msgUser));
            }
            if(!userInfos.isEmpty()) {
                MsgQueue.MsgInfo msgInfo = msgQueue.new MsgInfo().setBizMsgThresholdId(thresholdId)
                        .setThresholdSet(bizMsgThresholdVO.getThresholdContent()).setRoleIds(super.roleList);
                msgQueue.addOperator(msgQueue.new PushMsgOperator(userInfos, msgInfo));
            }
        } else {
            bizMsgUser.setId(CommonUtil.getUUID());

            userInfos.add(msgQueue.new BizMsgUserInfo().setValid(false).setBizMsgUser(bizMsgUser));

            MsgQueue.MsgInfo msgInfo = msgQueue.new MsgInfo().setBizMsgThresholdId(thresholdId)
                    .setThresholdSet(bizMsgThresholdVO.getThresholdContent());
            msgQueue.addOperator(msgQueue.new PushMsgOperator(userInfos, msgInfo));
        }
        super.roleList = null;
    }

    @Override
    public boolean valiIsPush(Map<String, Object> valiMap) {
        return false;
    }

}
